package net.sansi.v3correctserver.dto;

import cn.hutool.core.date.DateTime;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.experimental.Accessors;

/**
 * Created by Fang
 * create time : 2023/12/20
 * IDE : IntelliJ IDEA
 * <p>
 * 通用返回类
 * 一些通用的返回信息可以在这里定义
 * <p>
 * 返回格式：
 * {
 * "code": 200, // 错误码
 * "message": "成功", // 消息，一般是错误信息
 * "data": T  // 实际返回数据
 * "timestamp": 1608451200000 // 时间戳
 * validateFailed: HashMap<String, Object> || null // 校验失败时返回的数据
 * sign: String || null // 签名（如果需要的话）
 * }
 * <p>
 * }
 * 常用返回码：
 * 100：常规错误，建议前端直接弹出错误信息
 * 101：常规错误，不建议前端直接弹出错误信息
 * 102：校验错误，在validateFailed中返回校验失败的字段和原因
 * 200：成功
 * 401：未登录
 * 403：无权限
 */
@Data
@Accessors(chain = true)
@ApiModel("统一响应结构体")
public class R<T> {

    // 常用返回码
    public static final int SUCCESS = 200;
    // 常规错误，建议前端直接弹出错误信息
    public static final int ERROR = 100;
    // 常规错误，不建议前端直接弹出错误信息
    public static final int ERROR_NO_ALERT = 101;
    // 校验错误，在validateFailed中返回校验失败的字段和原因
    public static final int VALIDATE_FAILED = 102;
    // 未登录
    public static final int NOT_LOGIN = 401;
    // 无权限
    public static final int NO_PERMISSION = 403;
    // 未绑定任何租户
    public static final int NO_TENANT = 404;


    // 成功返回的默认信息
    public static final String SUCCESS_MSG = "success";
    // 错误返回的默认信息
    public static final String ERROR_MSG = "error";


    // 返回码
    @ApiModelProperty("状态码")
    private int code;
    // 消息，一般是错误信息
    @ApiModelProperty("消息，一般为错误消息")
    private String message;
    // 返回的数据
    @ApiModelProperty("返回数据")
    private T data;
    // 时间戳
    @ApiModelProperty("时间戳")
    private long timestamp;
    // 校验失败时返回的数据
    @ApiModelProperty("验证错误信息")
    private Object validateFailed;
    // 签名（如果需要的话）
    @ApiModelProperty("签名，如果有的话")
    private String sign;


    /**
     * 返回成功信息
     *
     * @param data 返回的数据
     * @param <T>  T
     * @return R
     */
    public static <T> R<T> data(T data) {
        return new R<T>().setCode(SUCCESS).setMessage(SUCCESS_MSG).setData(data);
    }

    /**
     * 返回错误信息
     *
     * @param msg 错误信息
     * @return R 错误信息
     */
    public static <T> R<T> error(String msg) {
        return new R<T>().setCode(ERROR).setMessage(msg);
    }

    /**
     * 返回错误信息
     * 默认错误信息为：error
     *
     * @return R 错误信息
     */
    public static <T> R<T> error() {
        return new R<T>().setCode(ERROR).setMessage(ERROR_MSG);
    }

    /**
     * 成功返回
     *
     * @param msg 成功信息
     * @param <T> T
     * @return R
     */
    public static <T> R<T> success(String msg) {
        return new R<T>().setCode(SUCCESS).setMessage(msg);
    }

    /**
     * 成功返回
     *
     * @param <T> T
     * @return R
     */
    public static <T> R<T> success() {
        return new R<T>().setCode(SUCCESS).setMessage(SUCCESS_MSG);
    }

    /**
     * 根据状态返回成功或失败
     *
     * @param success 状态 true 成功，false 失败
     * @return R
     */
    public static R<String> status(boolean success) {
        return success ? success() : error();
    }

    /**
     * 根据状态返回成功或失败
     *
     * @return R
     */
    public boolean isSuccess() {
        return this.code == SUCCESS;
    }


    /**
     * 获取时间戳
     *
     * @return 时间戳
     */
    public Long getTimestamp() {
        return DateTime.now().getTime() / 1000;
    }

}
